/*
 * G4SipmEffectiveOvervoltageCellFireController.cc
 *
 * @date Feb 17, 2014
 * @author Tim Niggemann, III Phys. Inst. A, RWTH Aachen University
 * @copyright GNU General Public License v3.0
 */

#include <digi/G4SipmEffectiveOvervoltageCellFireController.hh>

#include <CLHEP/Units/SystemOfUnits.h>
#include <CLHEP/Random/RandFlat.h>

#include "G4SipmUiMessenger.hh"
// 构造函数
G4SipmEffectiveOvervoltageCellFireController::G4SipmEffectiveOvervoltageCellFireController(G4SipmModel *_model,
																						   double t0) : G4SipmCellFireController(_model, t0)
{
	// 过电压，这里用的是模型中的过电压
	effectiveOvervoltage = model->getOverVoltage();
	// 分流电阻，这里用的是50欧姆
	shuntResistor = 50. * CLHEP::ohm;
	// 猝灭电阻，这里用的是151.2k欧姆
	quenchingResistor = 151.2e3 * CLHEP::ohm;
	// 上一个脉冲时间，这里用的是t0
	tLast = t0;
	// 累积脉冲数，这里用的是1
	nCoincident = 1;
	// Recharge time constant for a 50 Ohm shunt resistor and Hamamatsu 3x3 50 mu pitch: 30.12 * CLHEP::nanosecond.
	// 计算恢复时间常数，这里用的是50 Ohm分流电阻和Hamamatsu 3x3 50 mu pitch的恢复时间常数，大概是30.12纳秒
	tau = G4SipmUiMessenger::getInstance()->getShuntresistorRecoveryTime();
	//	vu = 0.0002104984 * CLHEP::volt;
	//	vu = 0.00033 * CLHEP::volt;
	// SiPM的激发电压，这里用的是分流电阻和猝灭电阻的比值乘以过电压
	vu = model->getOverVoltage() * shuntResistor / (quenchingResistor + shuntResistor);
}
// 计算恢复电压，模拟电容器充电的计算公式，这里用的是指数衰减函数
inline double rechargeOvervoltage(double dt, double vEff, double vOv, double tau)
{
	double t1 = -tau * log(1. - vEff / vOv);
	return vOv * (1. - exp(-(t1 + dt) / tau));
}
// 脉冲触发函数，这里用的是有效过电压和模型中的过电压的比值乘以模型的增益
bool G4SipmEffectiveOvervoltageCellFireController::fire(G4SipmDigi *d)
{
	double &cellTime = cellIdToTimeMap[d->getCellId()];
	// Check timing.
	// 时间过滤，这里用的是模型中的死时间
	if (G4SipmUiMessenger::getInstance()->isFilterTiming())
	{
		if (cellTime + model->getDeadTime() >= d->getTime() || d->getCellId() >= model->getNumberOfCells() || d->getWeight() <= 0.)
		{
			return false;
		}
	}
	// Account for the PDE drop linearly with the over voltage.
	// 考虑PDE下降与过电压呈线性关系。
	if (d->getType() == PHOTON)
	{
		if (CLHEP::RandFlat::shoot() > effectiveOvervoltage / model->getOverVoltage())
		{
			return false;
		}
	}
	// Recharge effective over voltage.
	// 重新充电有效过电压，这里用的是指数衰减函数
	effectiveOvervoltage = rechargeOvervoltage(d->getTime() - tLast /* - model->getDeadTime()*/, effectiveOvervoltage,
											   model->getOverVoltage(), tau);
	// Determine gain from the recovery behaviour of the capacitor in the diode equivalent circuit.
	// 计算增益，这里用的是指数衰减函数
	double gain = 1. - exp(-(d->getTime() - cellTime - model->getDeadTime()) / model->getRecoveryTime());
	// Update weight of the digi and include gain variation.
	// 更新digi的权重，包括增益变化
	d->setWeight(gain * effectiveOvervoltage / model->getOverVoltage() * model->getGain(d->getCellId()));
	// If this pulse is a coincident pulse do not decrease effective overvoltage just yet.
	// 如果是连续脉冲，则不立即减少有效过电压
	if (d->getTime() <= tLast + model->getDeadTime())
	{
		nCoincident++;
	}
	else
	{
		// Reduce effective over voltage.
		// 减少有效过电压
		effectiveOvervoltage -= ((double)nCoincident) * vu * effectiveOvervoltage / model->getOverVoltage() * d->getWeight();
		effectiveOvervoltage = std::max(effectiveOvervoltage, 0.);
		nCoincident = 1;
	}
	// Update time.
	cellTime = d->getTime();
	tLast = d->getTime();
	// Success.
	return true;
}
